package com.mlethe.library.widget.banner;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.database.Observable;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import static androidx.viewpager.widget.ViewPager.SCROLL_STATE_DRAGGING;
import static androidx.viewpager.widget.ViewPager.SCROLL_STATE_IDLE;
import static androidx.viewpager.widget.ViewPager.SCROLL_STATE_SETTLING;

/**
 * 自定义BannerView
 * Created by Mlethe on 2018/5/29.
 */
public class BannerView extends RelativeLayout implements ViewPager.OnPageChangeListener {

    private AdapterDataObserver mObserver = new AdapterDataObserver();

    // 轮播的ViewPager
    private BannerViewPager mBannerVp;
    // 指示器的容器
    private LinearLayout mIndicatorContainerView;
    // 默认图片
    private ImageView mDefaultImageIv;
    // 底部进度条
    private ImageView mBottomProcessIv;
    // 自定义的BannerAdapter
    private BannerAdapter mAdapter;
    // ViewPager的adapter
    private BannerPagerAdapter mBannerAdapter;
    // ViewPager滚动动画
    private BannerScroller mScroller;
    // ViewPager滚动监听
    private BannerViewPager.OnRollingListener mOnRollingListener = new BannerViewPager.OnRollingListener() {
        @Override
        public long getRollTime(int position) {
            if (mAdapter == null || isCumRollTime) {
                return 0;
            }
            int count = mAdapter.getCount();
            if (count <= 0) {
                return 0;
            }
            int realPosition = position % count;
            return mAdapter.getRollTime(mAdapter.getData().get(realPosition), realPosition);
        }
    };
    // 当前position
    private int currentItem;
    // 内存优化界面复用 - 复用的界面
    private List<View> mConvertViews;

    // 当前指示器的位置
    private int mCurrentPosition = 0;
    // 指示器的显示位置 默认中间
    private int mIndicatorGravity = 0;
    // 指示器的间距
    private float mIndicatorDistance = 4;
    // 指示器PaddingBottom
    private float mIndicatorPaddingBottom = 10;
    // 指示器PaddingRight
    private float mIndicatorPaddingRight = 10;
    // 指示器PaddingLeft
    private float mIndicatorPaddingLeft = 10;
    // 指示器选中的Drawable的资源Id
    private int mIndicatorSelectedId = R.drawable.banner_default_indicator_focus;
    // 指示器默认的Drawable的资源Id
    private int mIndicatorNormalId = R.drawable.banner_default_indicator_normal;
    // 底部进度条的资源Id
    private int mBottomProcessId;
    // 是否自动轮播
    private boolean mIsAutoPlay = true;
    // 轮播间隔时间
    private int mDelayTime = 2000;
    // 动画持续的时间
    private int mScrollTime = 950;
    // 默认图片
    private int mDefaultImage;
    // 是否使用默认图片
    private boolean mIsDefaultImage = true;
    // 指示器指示器是否显示
    private boolean mIndicatorHide = false;
    // 是否使用底部进度条
    private boolean isUseBottomProcess = false;
    // 是否能使用手势滑动
    private boolean isCanSided = true;
    // 是否自定义滚动时间
    private boolean isCumRollTime = false;
    // 布局宽高尺寸比
    private float ratio = 0f;

    public BannerView(Context context) {
        this(context, null);
    }

    public BannerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BannerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 把布局加载到这个View里面
        inflate(context, R.layout.ui_banner_layout, this);
        initAttribute(context, attrs);
        initView();
    }

    /**
     * 初始化自定义属性
     */
    private void initAttribute(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerView);
//        mBottomHeight = (int) typedArray.getDimension(R.styleable.BannerView_bottomHeight, dip2px(mBottomHeight));
        // 获取指示器的显示位置
        mIndicatorGravity = typedArray.getInt(R.styleable.BannerView_indicatorGravity, mIndicatorGravity);
        mIndicatorHide = typedArray.getBoolean(R.styleable.BannerView_indicatorHide, mIndicatorHide);
        mIndicatorSelectedId = typedArray.getResourceId(R.styleable.BannerView_indicatorSelected, mIndicatorSelectedId);
        mIndicatorNormalId = typedArray.getResourceId(R.styleable.BannerView_indicatorNormal, mIndicatorNormalId);
        mIndicatorDistance = typedArray.getDimension(R.styleable.BannerView_indicatorDistance, dip2px(mIndicatorDistance));
        mIndicatorPaddingBottom = typedArray.getDimension(R.styleable.BannerView_indicatorPaddingBottom, dip2px(mIndicatorPaddingBottom));
        mIndicatorPaddingRight = typedArray.getDimension(R.styleable.BannerView_indicatorPaddingRight, dip2px(mIndicatorPaddingRight));
        mIndicatorPaddingLeft = typedArray.getDimension(R.styleable.BannerView_indicatorPaddingLeft, dip2px(mIndicatorPaddingLeft));
        mIsAutoPlay = typedArray.getBoolean(R.styleable.BannerView_isAutoPlay, mIsAutoPlay);
        mDelayTime = typedArray.getInt(R.styleable.BannerView_delayTime, mDelayTime);
        mScrollTime = typedArray.getInt(R.styleable.BannerView_scrollTime, mScrollTime);
        mDefaultImage = typedArray.getResourceId(R.styleable.BannerView_bannerDefaultImage, R.mipmap.bg_no_banner);
        mIsDefaultImage = typedArray.getBoolean(R.styleable.BannerView_isDefaultImage, mIsDefaultImage);
        isUseBottomProcess = typedArray.getBoolean(R.styleable.BannerView_isUseBottomProcess, isUseBottomProcess);
        mBottomProcessId = typedArray.getResourceId(R.styleable.BannerView_bottomProcess, mBottomProcessId);
        isCanSided = typedArray.getBoolean(R.styleable.BannerView_isCanSided, isCanSided);
        isCumRollTime = typedArray.getBoolean(R.styleable.BannerView_isCumRollTime, isCumRollTime);
        String layoutRatio = typedArray.getString(R.styleable.BannerView_layoutRatio);
        // （宽：高 => 4:1）
        if (!TextUtils.isEmpty(layoutRatio)) {
            String[] strings = layoutRatio.split(":");
            if (strings.length >= 2) {
                ratio = Float.valueOf(strings[0]) / Float.valueOf(strings[1]);
            }
        }
        typedArray.recycle();
    }

    /**
     * 初始化view
     */
    private void initView() {
        mBannerVp = findViewById(R.id.banner_vp);
        mIndicatorContainerView = findViewById(R.id.indicator_container);
        mDefaultImageIv = findViewById(R.id.banner_default_image_iv);
        mBottomProcessIv = findViewById(R.id.banner_process_iv);
        if (isUseBottomProcess) {
            mBottomProcessIv.setImageResource(mBottomProcessId);
        }
        if (mIsDefaultImage) {
            mDefaultImageIv.setImageResource(mDefaultImage);
        }
        mIndicatorContainerView.setPadding((int) mIndicatorPaddingLeft, 0, (int) mIndicatorPaddingRight, (int) mIndicatorPaddingBottom);
        // 配置BannerViewPager
        setBannerVpConfig();
    }

    /**
     * 初始化指示器
     */
    private void initIndicator() {
        mIndicatorContainerView.removeAllViews();
        // 获取广告位的数量
        int count = mAdapter.getCount();
        // 让指示器的位置在右边
        mIndicatorContainerView.setGravity(getIndicatorGravity());
        for (int i = 0; i < count; i++) {
            // 不断的往指示器容器添加指示器
            ImageView imageView = new ImageView(getContext());
            // 设置左右的间距
            if (i != 0) {
                imageView.setPadding((int) mIndicatorDistance, 0, 0, 0);
            }
            // 设置颜色
            if (i == 0) {
                // 选中位置
                imageView.setImageResource(mIndicatorSelectedId);
            } else {
                // 未选中的
                imageView.setImageResource(mIndicatorNormalId);
            }
            mIndicatorContainerView.addView(imageView);
        }
    }

    /**
     * 获取指示器的位置
     *
     * @return
     */
    private int getIndicatorGravity() {
        if (mIndicatorGravity == 0) {
            return Gravity.CENTER | Gravity.CENTER_VERTICAL;
        } else if (mIndicatorGravity == -1) {
            return Gravity.LEFT | Gravity.CENTER_VERTICAL;
        } else if (mIndicatorGravity == 1) {
            return Gravity.RIGHT | Gravity.CENTER_VERTICAL;
        }
        return Gravity.RIGHT | Gravity.CENTER_VERTICAL;
    }

    @Override
    protected void onDetachedFromWindow() {
        if (mAdapter != null) {
            mAdapter.unregisterAdapterDataObserver(mObserver);
            mAdapter.onDetachedFromBannerView(this);
            mAdapter = null;
        }
        if (mConvertViews != null) {
            mConvertViews.clear();
        }
        super.onDetachedFromWindow();
    }

    /**
     * 把dip转为px
     *
     * @param dip
     * @return
     */
    private float dip2px(float dip) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
    }

    /**
     * 把sp转为px
     *
     * @param sp
     * @return
     */
    private float sp2px(float sp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
    }

    /**
     * 设置适配器
     *
     * @param adapter
     */
    public void setAdapter(BannerAdapter adapter) {
        if (mAdapter != null) {
            mAdapter.unregisterAdapterDataObserver(mObserver);
            mAdapter.onDetachedFromBannerView(this);
            mAdapter = null;
        }
        if (mConvertViews != null) {
            mConvertViews.clear();
        }
        this.mAdapter = adapter;
        if (mAdapter != null) {
            mAdapter.registerAdapterDataObserver(mObserver);
            mAdapter.onAttachedToBannerView(this);
            if (mAdapter.getCount() > 0) {
                showViewPager();
                return;
            }
        }
        showEmptyView();
    }

    /**
     * 显示ViewPager
     */
    private void showViewPager() {
        currentItem = 0;
        mDefaultImageIv.setVisibility(GONE);
        mBannerVp.setVisibility(VISIBLE);
        mIndicatorContainerView.setVisibility(VISIBLE);
        if (!mIndicatorHide) {
            // 初始化指示器
            initIndicator();
        }
        mBannerAdapter.notifyDataSetChanged();
        mBannerVp.startRoll();
    }

    /**
     * 显示空数据view
     */
    private void showEmptyView() {
        mBannerAdapter.notifyDataSetChanged();
        mBannerVp.stopRoll();
        if (mIsDefaultImage) {
            mDefaultImageIv.setImageResource(mDefaultImage);
        }
        mDefaultImageIv.setVisibility(VISIBLE);
        mBannerVp.setVisibility(GONE);
        mIndicatorContainerView.setVisibility(GONE);
    }

    /**
     * BannerViewPager设置
     */
    private void setBannerVpConfig() {
        if (mConvertViews == null) {
            mConvertViews = new ArrayList<>();
        }
        mBannerAdapter = new BannerPagerAdapter();
        mBannerVp.setAdapter(mBannerAdapter);
        mBannerVp.setOnRollingListener(mOnRollingListener);
        mBannerVp.setCanSlided(isCanSided);
        mBannerVp.setAutoPlay(mIsAutoPlay);
        mBannerVp.setDelayTime(mDelayTime);
        // BannerViewPager切换回调
        mBannerVp.addOnPageChangeListener(this);
        // 改变ViewPager切换的速率
        // duration 持续的时间  局部变量
        // 改变 mScroller private 通过
        try {
            Field field = ViewPager.class.getDeclaredField("mScroller");
            // 设置参数  第一个object->当前属性在那个类  第二个参数代表要设置的值
            mScroller = new BannerScroller(getContext());
            // 设置为强制改变private
            field.setAccessible(true);
            field.set(mBannerVp, mScroller);
            mScroller.setScrollerDuration(mScrollTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        if (mIsAutoPlay) {
            if (visibility == VISIBLE) {
                mBannerVp.startRoll();
            } else {
                mBannerVp.stopRoll();
            }
        }
    }

    /**
     * 页面切换的回调
     *
     * @param position
     */
    private void pageSelected(int position) {
        // 把之前亮着的指示器 设置为默认
        ImageView oldIndicatorView = (ImageView) mIndicatorContainerView.getChildAt(mCurrentPosition);
        oldIndicatorView.setImageResource(mIndicatorNormalId);
        // 把当前位置的指示器 点亮
        mCurrentPosition = position % mAdapter.getCount();
        ImageView currentIndicatorView = (ImageView) mIndicatorContainerView.getChildAt(mCurrentPosition);
        currentIndicatorView.setImageResource(mIndicatorSelectedId);
    }

    /**
     * 是否禁止滑动
     *
     * @param canSided
     * @return
     */
    public BannerView setCanSided(boolean canSided) {
        this.isCanSided = canSided;
        if (mBannerVp != null) {
            mBannerVp.setCanSlided(isCanSided);
        }
        return this;
    }

    /**
     * 是否自定义滚动时间
     *
     * @param cumRollTime
     * @return
     */
    public BannerView setCumRollTime(boolean cumRollTime) {
        this.isCumRollTime = cumRollTime;
        return this;
    }

    /**
     * 设置使用使用底部进度条
     *
     * @param useBottomProcess
     * @return
     */
    public BannerView isUseBottomProcess(boolean useBottomProcess) {
        this.isUseBottomProcess = useBottomProcess;
        if (isUseBottomProcess) {
            mBottomProcessIv.setImageResource(mBottomProcessId);
        } else {
            mBottomProcessIv.setImageResource(0);
        }
        return this;
    }

    /**
     * 设置指示器是否隐藏
     *
     * @param indicatorHide
     */
    public BannerView setIndicatorHide(boolean indicatorHide) {
        this.mIndicatorHide = indicatorHide;
        if (!mIndicatorHide) {
            initIndicator();
        } else {
            if (mIndicatorContainerView != null) {
                mIndicatorContainerView.removeAllViews();
            }
        }
        return this;
    }

    /**
     * 设置轮播点击事件
     *
     * @param listener
     * @return
     */
    public BannerView setOnBannerItemListener(OnBannerItemListener listener) {
        this.mListener = listener;
        return this;
    }

    /**
     * 设置轮播动画时间
     *
     * @param scrollTime
     * @return
     */
    public BannerView setScrollTime(int scrollTime) {
        this.mScrollTime = scrollTime;
        if (mScroller != null) {
            mScroller.setScrollerDuration(mScrollTime);
        }
        return this;
    }

    /**
     * 设置轮播时间
     *
     * @param time
     * @return
     */
    public BannerView setDelayTime(int time) {
        this.mDelayTime = time;
        if (mBannerVp != null) {
            mBannerVp.setDelayTime(mDelayTime);
        }
        return this;
    }

    /**
     * 设置是否自动轮播
     *
     * @param isAutoPlay
     * @return
     */
    public BannerView setAutoPlay(boolean isAutoPlay) {
        this.mIsAutoPlay = isAutoPlay;
        if (mBannerVp != null) {
            mBannerVp.setAutoPlay(mIsAutoPlay);
        }
        return this;
    }

    /**
     * 设置选中指示器
     *
     * @param resId
     * @return
     */
    public BannerView setIndicatorSelected(int resId) {
        this.mIndicatorSelectedId = resId;
        if (!mIndicatorHide) {
            initIndicator();
        }
        return this;
    }

    /**
     * 设置默认指示器
     *
     * @param resId
     * @return
     */
    public BannerView setIndicatorNormal(int resId) {
        this.mIndicatorNormalId = resId;
        if (!mIndicatorHide) {
            initIndicator();
        }
        return this;
    }

    /**
     * 设置底部进度条指示器
     *
     * @param resId
     * @return
     */
    public BannerView setBottomProcessDrawable(int resId) {
        this.mBottomProcessId = resId;
        if (isUseBottomProcess) {
            mBottomProcessIv.setImageResource(mBottomProcessId);
        }
        return this;
    }

    /**
     * 设置指示器padding（单位dp）
     *
     * @param left
     * @param right
     * @param bottom
     * @return
     */
    public BannerView setIndicatorPadding(float left, float right, float bottom) {
        mIndicatorPaddingLeft = dip2px(left);
        mIndicatorPaddingRight = dip2px(right);
        mIndicatorPaddingBottom = dip2px(bottom);
        mIndicatorContainerView.setPadding((int) mIndicatorPaddingLeft, 0, (int) mIndicatorPaddingRight, (int) mIndicatorPaddingBottom);
        return this;
    }

    /**
     * 设置ViewPagerPadding（单位dp）
     *
     * @param left
     * @param top
     * @param right
     * @param bottom
     * @return
     */
    public BannerView setViewPagerPadding(float left, float top, float right, float bottom) {
        mBannerVp.setPadding((int) dip2px(left), (int) dip2px(top), (int) dip2px(right), (int) dip2px(bottom));
        return this;
    }

    /**
     * 设置ViewPagerMargin（单位dp）
     *
     * @param left
     * @param top
     * @param right
     * @param bottom
     * @return
     */
    public BannerView setViewPagerMargin(float left, float top, float right, float bottom) {
        LayoutParams layoutParams = (LayoutParams) mBannerVp.getLayoutParams();
        layoutParams.leftMargin = (int) dip2px(left);
        layoutParams.topMargin = (int) dip2px(top);
        layoutParams.rightMargin = (int) dip2px(right);
        layoutParams.bottomMargin = (int) dip2px(bottom);
        mBannerVp.setLayoutParams(layoutParams);
        return this;
    }

    public BannerView setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {
        mBannerVp.setPageTransformer(reverseDrawingOrder, transformer);
        return this;
    }

    /**
     * 启动自动轮播（Fragment show的时候setUserVisibleHint中调用）
     *
     * @return
     */
    public void start() {
        mBannerVp.startRoll();
    }

    /**
     * 停止自动轮播（Fragment hide的时候setUserVisibleHint中调用）
     *
     * @return
     */
    public void stop() {
        mBannerVp.stopRoll();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
        //获取宽度的模式和尺寸
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (ratio > 0) {
            if (widthSize == 0) {
                // 根据宽高比ratio和模式创建一个测量值
                widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (heightSize * ratio), MeasureSpec.EXACTLY);
            } else if (heightSize == 0) {
                // 根据宽高比ratio和模式创建一个测量值
                heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (widthSize / ratio), MeasureSpec.EXACTLY);
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 给ViewPager设置适配器
     */
    private class BannerPagerAdapter extends PagerAdapter {

        private LayoutInflater inflater;

        public BannerPagerAdapter() {
            inflater = LayoutInflater.from(getContext());
        }

        @Override
        public int getCount() {
            if (mAdapter == null) {
                return 0;
            } else {
                int count = mAdapter.getCount();
                if (count <= 0) {
                    return 0;
                } else if (count == 1) {
                    return 1;
                }
            }
            // 为了实现无限循环
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            // 官方推荐这么写  源码
            return view == object;
        }

        /**
         * 创建ViewPager条目回调的方法
         *
         * @param container
         * @param position
         * @return
         */
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            if (mAdapter == null) {
                return super.instantiateItem(container, position);
            }
            int count = mAdapter.getCount();
            if (count <= 0) {
                return super.instantiateItem(container, position);
            }
            final int realPosition = position % count;
            // Adapter设计模式是为了完全让用自定义
            Object item = mAdapter.getData().get(realPosition);
            int layoutId = mAdapter.getLayoutId(item, realPosition);
            View view = getConvertView(layoutId);
            if (view == null) {
                view = inflater.inflate(layoutId, container, false);
            }
            if (mListener != null) {
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mListener != null) {
                            mListener.onClick(realPosition);
                        }
                    }
                });
            }
            // position 0 -> 2的31次方
            ViewHolder holder = new ViewHolder(view);
            mAdapter.convert(holder, item, realPosition);
            // 添加ViewPager里面
            container.addView(view);
            return view;
        }

        /**
         * 销毁条目回调的方法
         *
         * @param container
         * @param position
         * @param object
         */
        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
            mConvertViews.add((View) object);
            object = null;
        }

        @Override
        public void unregisterDataSetObserver(@NonNull DataSetObserver observer) {
            inflater = null;
            super.unregisterDataSetObserver(observer);
        }
    }

    /**
     * 获取复用界面
     *
     * @return
     */
    private View getConvertView(int layoutId) {
        for (View convertView : mConvertViews) {
            if (convertView.getParent() == null && convertView.getId() == layoutId) {
                return convertView;
            }
        }
        return null;
    }

    private ObjectAnimator translationXAnimator;

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (isUseBottomProcess) {
            mBottomProcessIv.setTranslationX(positionOffsetPixels * (-1));
            if (positionOffset <= 0) {
                mBottomProcessIv.setVisibility(GONE);
            }
        }
    }

    @Override
    public void onPageSelected(int position) {
        currentItem = position;
        if (!mIndicatorHide) {
            // 监听当前选中的位置
            pageSelected(position);
        }
        final int realPosition = position % mAdapter.getCount();
        mAdapter.onCurrentItem(mAdapter.getData().get(realPosition), realPosition);
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        switch (state) {
            case SCROLL_STATE_IDLE:
                // 什么都没做
                if (currentItem == 0) {
                    mBannerVp.setCurrentItem(mAdapter.getCount(), false);
                }
                if (isUseBottomProcess) {
                    translationXAnimator = ObjectAnimator.ofFloat(mBottomProcessIv, "translationX", getWidth() * (-1), 0)
                            .setDuration(mDelayTime - mScrollTime);
                    translationXAnimator.setInterpolator(new LinearInterpolator());
                    translationXAnimator.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationStart(Animator animation) {
                            mBottomProcessIv.setVisibility(VISIBLE);
                            mBottomProcessIv.setTranslationX(getWidth() * (-1));
                        }
                    });
                    translationXAnimator.start();
                }
                break;
            case SCROLL_STATE_DRAGGING:
                // 开始滑动
                if (currentItem == 0) {
                    mBannerVp.setCurrentItem(mAdapter.getCount(), false);
                }
                if (isUseBottomProcess) {
                    if (translationXAnimator != null) {
                        translationXAnimator.cancel();
                    }
                    mBottomProcessIv.setVisibility(GONE);
                }
                break;
            case SCROLL_STATE_SETTLING:
                // 滑动结束
                break;
        }
    }

    private OnBannerItemListener mListener;

    public interface OnBannerItemListener {
        void onClick(int position);
    }

    static class AdapterDataObservable extends Observable<AdapterDataObserver> {
        public void notifyChanged() {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }

    public class AdapterDataObserver {
        public void onChanged() {
            // Do nothing
            if (mAdapter != null) {
                if (mAdapter.getCount() > 0) {
                    if (mBannerVp.getVisibility() != VISIBLE) {
                        mDefaultImageIv.setVisibility(GONE);
                        mBannerVp.setVisibility(VISIBLE);
                        mIndicatorContainerView.setVisibility(VISIBLE);
                    }
                    if (!mIndicatorHide) {
                        // 初始化指示器
                        initIndicator();
                    }
                    mBannerAdapter.notifyDataSetChanged();
                    mBannerVp.startRoll();
                    return;
                }
            }
            showEmptyView();
        }
    }

    /**
     * Created by Mlethe on 2018/4/29.
     */
    public static class ViewHolder {

        // 用来存放子View减少findViewById的次数
        private SparseArray<View> mViews;

        protected View mItemView;

        public ViewHolder(View itemView) {
            this.mItemView = itemView;
            mViews = new SparseArray<>();
        }

        /**
         * 设置TextView提示
         *
         * @param viewId
         * @param text
         * @return
         */
        public ViewHolder setHint(@IdRes int viewId, CharSequence text) {
            TextView tv = getView(viewId);
            tv.setHint(text);
            return this;
        }

        /**
         * 设置TextView提示
         *
         * @param viewId
         * @param resid
         * @return
         */
        public ViewHolder setHint(@IdRes int viewId, @StringRes int resid) {
            TextView tv = getView(viewId);
            tv.setHint(resid);
            return this;
        }

        /**
         * 设置TextView提示
         *
         * @param viewId
         * @param value
         * @return
         */
        public ViewHolder setHint(@IdRes int viewId, float value) {
            setHint(viewId, String.valueOf(value));
            return this;
        }

        /**
         * 设置TextView提示
         *
         * @param viewId
         * @param value
         * @return
         */
        public ViewHolder setHint(@IdRes int viewId, double value) {
            setHint(viewId, String.valueOf(value));
            return this;
        }

        /**
         * 设置TextView提示
         *
         * @param viewId
         * @param value
         * @return
         */
        public ViewHolder setHint(@IdRes int viewId, long value) {
            setHint(viewId, String.valueOf(value));
            return this;
        }

        /**
         * 设置TextView文本
         *
         * @param viewId viewId
         * @param text   text
         * @return ViewHolder
         */
        public ViewHolder setText(@IdRes int viewId, CharSequence text) {
            TextView view = getView(viewId);
            view.setText(text);
            return this;
        }

        /**
         * 设置TextView文本
         *
         * @param viewId viewId
         * @param resId  resId
         * @return ViewHolder
         */
        public ViewHolder setText(int viewId, @StringRes int resId) {
            TextView view = getView(viewId);
            view.setText(resId);
            return this;
        }

        /**
         * 设置TextView文本
         *
         * @param viewId viewId
         * @param value  value
         * @return ViewHolder
         */
        public ViewHolder setText(@IdRes int viewId, float value) {
            setText(viewId, String.valueOf(value));
            return this;
        }

        /**
         * 设置TextView文本
         *
         * @param viewId viewId
         * @param value  value
         * @return ViewHolder
         */
        public ViewHolder setText(@IdRes int viewId, double value) {
            setText(viewId, String.valueOf(value));
            return this;
        }

        /**
         * 设置TextView文本
         *
         * @param viewId viewId
         * @param value  value
         * @return ViewHolder
         */
        public ViewHolder setText(@IdRes int viewId, long value) {
            setText(viewId, String.valueOf(value));
            return this;
        }

        /**
         * 通过id获取view
         */
        @SuppressWarnings("unchecked")
        public <T extends View> T getView(@IdRes int viewId) {
            // 先从缓存中找
            View view = mViews.get(viewId);
            if (view == null) {
                // 直接从ItemView中找
                view = mItemView.findViewById(viewId);
                mViews.put(viewId, view);
            }
            return (T) view;
        }

        /**
         * 设置View的Visibility
         *
         * @param viewId     viewId
         * @param visibility visibility
         * @return ViewHolder
         */
        public ViewHolder setVisibility(@IdRes int viewId, @Visibility int visibility) {
            getView(viewId).setVisibility(visibility);
            return this;
        }

        /**
         * 获取View的Visibility
         *
         * @param viewId viewId
         * @return Visibility
         */
        public int getVisibility(@IdRes int viewId) {
            return getView(viewId).getVisibility();
        }

        /**
         * @param viewId    viewId
         * @param scaleType ScaleType
         * @return ViewHolder
         */
        public ViewHolder setScaleType(@IdRes int viewId, @NonNull ImageView.ScaleType scaleType) {
            ImageView view = getView(viewId);
            view.setScaleType(scaleType);
            return this;
        }

        /**
         * 为ImageView设置图片
         *
         * @param viewId     viewId
         * @param resourceId resourceId
         * @return ViewHolder
         */
        public ViewHolder setImageResource(@IdRes int viewId, @DrawableRes int resourceId) {
            ImageView view = getView(viewId);
            view.setImageResource(resourceId);
            return this;
        }

        /**
         * 为ImageView设置图片
         *
         * @param viewId viewId
         * @param bm     Bitmap
         * @return ViewHolder
         */
        public ViewHolder setImageBitmap(@IdRes int viewId, @NonNull Bitmap bm) {
            ImageView view = getView(viewId);
            view.setImageBitmap(bm);
            return this;
        }

        /**
         * 设置图片通过路径,这里稍微处理得复杂一些，因为考虑加载图片的第三方可能不太一样
         * 也可以直接写死
         *
         * @param viewId      viewId
         * @param imageEngine imageEngine
         * @return ViewHolder
         */
        public ViewHolder setImageByUrl(@IdRes int viewId, ImageEngine imageEngine) {
            ImageView view = getView(viewId);
            if (imageEngine == null) {
                throw new NullPointerException("imageEngine is null!");
            }
            imageEngine.displayImage(view.getContext(), view, imageEngine.getImagePath());
            return this;
        }

        /**
         * 设置View的点击事件
         *
         * @param viewId   viewId
         * @param listener listener
         * @return ViewHolder
         */
        public ViewHolder setOnClickListener(@IdRes int viewId, View.OnClickListener listener) {
            getView(viewId).setOnClickListener(listener);
            return this;
        }

        /**
         * 设置View的长按事件
         *
         * @param viewId   viewId
         * @param listener listener
         * @return ViewHolder
         */
        public ViewHolder setOnLongClickListener(@IdRes int viewId, View.OnLongClickListener listener) {
            getView(viewId).setOnLongClickListener(listener);
            return this;
        }
    }

    @IntDef({View.VISIBLE, View.INVISIBLE, View.GONE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Visibility {
    }

    /**
     * 图片加载，这里稍微处理得复杂一些，因为考虑加载图片的第三方可能不太一样
     * 也可以不写这个类
     */
    public static abstract class ImageEngine {
        private String mImagePath;

        public ImageEngine(String imagePath) {
            this.mImagePath = imagePath;
        }

        public String getImagePath() {
            return mImagePath;
        }

        public abstract void displayImage(Context context, ImageView imageView, String imagePath);
    }
}
